package it.antonio.ilpizze.servlet.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PathMacher {
	
	public static final String FILTER = "FILTER_PATH_MATCHER";
	private static final String PATH_SEPARATOR = "/";
	
	private final List<Matcher> path;
	private boolean filter;
	
	
	public static PathMacher parse(String path){
		
		List<Matcher> paths = new ArrayList<Matcher>();
		if(path == null || path.equals("") || path.equals(PATH_SEPARATOR)){
			 paths.add(new NoPathMatcher());
			return new PathMacher(paths);
		}
		
		// filter
		if(path.equals(FILTER)){
			PathMacher matcher = new PathMacher(paths);
			matcher.filter = true;
			return matcher;
		}
			
		
		
		String[] pieces = path.split(PATH_SEPARATOR);

		for (String piece : pieces) {
        	if(piece.startsWith("{") && piece.endsWith("}")){
        		paths.add(new StoringMatcher(piece));
        	} else {
        		paths.add(new SimpleMatcher(piece));	
        	}
        	
        }
        return new PathMacher(paths);
	}
	
	private PathMacher(List<Matcher> path) {
		super();
		this.path = path;
	}
	
	public Map<String, String> match(String incoming) {
		// handling FILTER
		if(filter) {
			return new HashMap<String, String>();
		}
		
		// handling empty url
		if(incoming == null || incoming.equals("") || incoming.equals(PATH_SEPARATOR)){
			if(path.size() == 1 && path.get(0) instanceof NoPathMatcher) {
				return new HashMap<String, String>();
			} else {
				return null;
			}
		} 
		
		// handling normal path
		String[] pieces = incoming.split(PATH_SEPARATOR);
        int i = 0;

        if (path.size() > pieces.length)
            return null;

        Map<String, String> values = new HashMap<String, String>();
        
        for (Matcher pathMatcher : path) {

        	
            if (i == pieces.length){
            	return pathMatcher.match("") ? values : null;   
            }

            String piece = pieces[i];

            // not match
            if (!pathMatcher.match(piece)){
            	return null;
            }
                

            final String name = pathMatcher.name();
            if (null != name){
            	values.put(name, piece);
            }
                
            i++;
        }
		
        return (i == pieces.length) ? values : null;
	}

	private interface Matcher {
		public boolean match(String path);
		public String name();
	}
	
	private static class NoPathMatcher implements Matcher {
		
		@Override
		public boolean match(String path) {
			return true;
		}

		@Override
		public String name() {
			return null;
		}
		
	}
	
	private static class SimpleMatcher implements Matcher {
		private String path;
		
		public SimpleMatcher(String path) {
			super();
			this.path = path;
		}

		@Override
		public boolean match(String path) {
			return this.path.equals(path);
		}

		@Override
		public String name() {
			return null;
		}
		
	}
	
	private static class StoringMatcher implements Matcher {
		private String path;
		
		public StoringMatcher(String path) {
			super();
			this.path = path.substring(1,path.length()-1);
		}

		@Override
		public boolean match(String path) {
			return true;
		}

		@Override
		public String name() {
			return path;
		}
		
	}
	
}
